/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cj_ability_object.h"

#include "hilog.h"

using namespace Keels;
using namespace Keels::AppExecFwk;
using namespace Keels::AbilityRuntime;
using namespace Keels::AbilityRuntime::Platform;

using WantHandle = void*;

namespace {
// g_cjAbilityFuncs is used to save cj functions.
// It is assigned by the global variable REGISTER_ABILITY on the cj side which invokes RegisterCJAbilityFuncs.
// And it is never released.
CJAbilityFuncs* g_cjAbilityFuncs = nullptr;
} // namespace

void RegisterCJAbilityFuncs(void (*registerFunc)(CJAbilityFuncs*))
{
    HILOG_INFO("RegisterCJAbilityFuncs called");
    if (g_cjAbilityFuncs != nullptr) {
        HILOG_ERROR("repeated registration for cj functions");
        return;
    }

    if (registerFunc == nullptr) {
        HILOG_ERROR("null registerFunc");
        return;
    }

    g_cjAbilityFuncs = new CJAbilityFuncs();
    registerFunc(g_cjAbilityFuncs);
    HILOG_INFO("RegisterCJAbilityFuncs end");
}

namespace Keels {
namespace AbilityRuntime {
namespace Platform {
std::shared_ptr<CJAbilityObject> CJAbilityObject::LoadModule(const std::string& name)
{
    if (g_cjAbilityFuncs == nullptr) {
        HILOG_ERROR("null cjAbilityFunc");
        return nullptr;
    }
    auto id = g_cjAbilityFuncs->cjAbilityCreate(name.c_str());
    if (id == 0) {
        HILOG_ERROR("failed to invoke , ability: %{public}s is not registered", name.c_str());
        return nullptr;
    }
    return std::make_shared<CJAbilityObject>(id);
}

CJAbilityObject::~CJAbilityObject()
{
    if (g_cjAbilityFuncs != nullptr) {
        g_cjAbilityFuncs->cjAbilityRelease(id_);
    }
    id_ = 0;
}

void CJAbilityObject::OnCreate(const AAFwk::Want& want, const LaunchParam& launchParam) const
{
    if (g_cjAbilityFuncs == nullptr) {
        HILOG_ERROR("null cjAbilityFunc");
        return;
    }
    WantHandle wantHandle = const_cast<AAFwk::Want*>(&want);
    CJLaunchParam param;
    param.launchReason = launchParam.launchReason;
    param.lastExitReason = launchParam.lastExitReason;
    param.lastExitMessage = "exit 0."; // TODO: 临时值
    g_cjAbilityFuncs->cjAbilityOnStart(id_, wantHandle, param);
}

// void CJAbilityObject::OnStop() const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return;
//     }
//     g_cjAbilityFuncs->cjAbilityOnStop(id_);
// }

void CJAbilityObject::OnWindowStageCreated(Keels::Rosen::CJWindowStageImpl* cjWindowStage) const
{
    if (g_cjAbilityFuncs == nullptr) {
        HILOG_ERROR("null cjAbilityFunc");
        return;
    }
    WindowStagePtr windowStage = reinterpret_cast<WindowStagePtr>(cjWindowStage);
    g_cjAbilityFuncs->cjAbilityOnSceneCreated(id_, windowStage);
}

// void CJAbilityObject::OnSceneRestored(Keels::Rosen::CJWindowStageImpl* cjWindowStage) const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return;
//     }
//     WindowStagePtr windowStage = reinterpret_cast<WindowStagePtr>(cjWindowStage);
//     g_cjAbilityFuncs->cjAbilityOnSceneRestored(id_, windowStage);
// }

// void CJAbilityObject::OnSceneDestroyed() const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return;
//     }
//     g_cjAbilityFuncs->cjAbilityOnSceneDestroyed(id_);
// }

void CJAbilityObject::OnForeground(const Want& want) const
{
    if (g_cjAbilityFuncs == nullptr) {
        HILOG_ERROR("null cjAbilityFunc");
        return;
    }
    WantHandle wantHandle = const_cast<AAFwk::Want*>(&want);
    g_cjAbilityFuncs->cjAbilityOnForeground(id_, wantHandle);
}

// void CJAbilityObject::OnBackground() const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return;
//     }
//     g_cjAbilityFuncs->cjAbilityOnBackground(id_);
// }

// void CJAbilityObject::OnConfigurationUpdated(const std::shared_ptr<AppExecFwk::Configuration>& configuration) const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return;
//     }
// }

// void CJAbilityObject::OnNewWant(const AAFwk::Want& want, const AAFwk::LaunchParam& launchParam) const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return;
//     }
//     WantHandle wantHandle = const_cast<AAFwk::Want*>(&want);
//     CJLaunchParam param;
//     param.launchReason = launchParam.launchReason;
//     param.lastExitReason = launchParam.lastExitReason;
//     g_cjAbilityFuncs->cjAbilityOnNewWant(id_, wantHandle, param);
// }

// void CJAbilityObject::Dump(const std::vector<std::string>& params, std::vector<std::string>& info) const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return;
//     }

//     VectorStringHandle paramHandle = const_cast<std::vector<std::string>*>(&params);
//     VectorStringHandle cjInfo = g_cjAbilityFuncs->cjAbilityDump(id_, paramHandle);
//     if (cjInfo == nullptr) {
//         HILOG_ERROR("null cj info");
//         return;
//     }

//     auto infoHandle = reinterpret_cast<std::vector<std::string>*>(cjInfo);
//     for (std::string item : *infoHandle) {
//         info.push_back(item);
//     }
//     // infoHandle is created in cj.
//     delete infoHandle;
//     infoHandle = nullptr;
// }

// int32_t CJAbilityObject::OnContinue(AAFwk::WantParams& wantParams) const
// {
//     if (g_cjAbilityFuncs == nullptr) {
//         HILOG_ERROR("null cjAbilityFunc");
//         return ContinuationManager::OnContinueResult::REJECT;
//     }
//     return 0;
// }

void CJAbilityObject::Init(AbilityHandle ability) const
{
    if (g_cjAbilityFuncs == nullptr) {
        HILOG_ERROR("null cjAbilityFunc");
        return;
    }
    g_cjAbilityFuncs->cjAbilityInit(id_, ability);
}
} // namespace Platform
} // namespace AbilityRuntime
} // namespace Keels
